package org.dromara.common.mybatis.handler;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.StringUtils;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;


/**
 * @Author 刘武贵
 * @Date 2024/8/15 22:00
 * @Description 功能描述：Mybatis异常处理器
 */
@Slf4j
/**
 * 定义一个全局异常处理器，专门处理Mybatis相关的异常
 */
@RestControllerAdvice
public class MybatisExceptionHandler {

    /**
     * 主键或UNIQUE索引，数据重复异常
     * 当插入或更新操作违反了主键约束或唯一约束时触发
     *
     * @param e 异常对象，包含错误详情
     * @param request HTTP请求对象，用于获取请求的URI
     * @return 返回一个R对象，包含操作结果，此处用于传达错误信息
     */
    @ExceptionHandler(DuplicateKeyException.class)
    public R<Void> handleDuplicateKeyException(DuplicateKeyException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        log.error("请求地址'{}',数据库中已存在记录'{}'", requestURI, e.getMessage());
        return R.fail("数据库中已存在该记录，请联系管理员确认");
    }

    /**
     * Mybatis系统异常 通用处理
     * 主要处理MyBatisSystemException异常，此类异常可能由多种原因触发，包括但不限于数据源未找到等
     *
     * @param e 异常对象，包含错误详情
     * @param request HTTP请求对象，用于获取请求的URI
     * @return 返回一个R对象，包含操作结果，此处用于传达错误信息
     */
    @ExceptionHandler(MyBatisSystemException.class)
    public R<Void> handleCannotFindDataSourceException(MyBatisSystemException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();
        String message = e.getMessage();
        if (StringUtils.contains("CannotFindDataSourceException", message)) {
            log.error("请求地址'{}', 未找到数据源", requestURI);
            return R.fail("未找到数据源，请联系管理员确认");
        }
        log.error("请求地址'{}', Mybatis系统异常", requestURI, e);
        return R.fail(message);
    }

}
